package com.monitor.api;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.AbstractHandlerMethodMapping;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;

import com.ms.MsConfig;
import com.ms.client.monitor.api.pojo.PrjApi;
import com.ms.client.monitor.api.service.ApiPrjApiService;
import com.ms.msclient.MsClientResponse;
import com.system.comm.utils.FrameJsonUtil;
import com.system.comm.utils.FrameSpringBeanUtil;
import com.system.handle.model.ResponseCode;

/**
 * 请求服务端的工具类
 * @author yuejing
 * @date 2016年10月21日 下午7:57:10
 * @version V1.0.0
 */
public class ApiUtil {

	private static final Logger LOGGER = LoggerFactory.getLogger(ApiUtil.class);

	/** API测试访问当前项目的ClientId */
	//public static String prjId;
	/** API测试访问当前项目的token */
	//public static String prjToken;

	/**
	 * 获取所有请求的路径<br>
	 * 注意: 
	 * 	map.get("name")		文字描叙
	 * 	map.get("path")		请求路径
	 * 	map.get("method")	方法的描叙字符串
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static List<Map<String, String>> findAll() {
		List<Map<String, String>> data = new ArrayList<Map<String, String>>();
		AbstractHandlerMethodMapping mapping = FrameSpringBeanUtil.getBean("requestMappingHandlerMapping");
		Map<RequestMappingInfo, HandlerMethod> hmMap = mapping.getHandlerMethods();
		Iterator<Entry<RequestMappingInfo, HandlerMethod>> entryKeyIterator = hmMap.entrySet().iterator();
		while (entryKeyIterator.hasNext()) {
			Entry<RequestMappingInfo, HandlerMethod> e = entryKeyIterator.next();
			HandlerMethod value = e.getValue();
			RequestMappingInfo rmi = e.getKey();
			Annotation[] anns = value.getMethod().getDeclaredAnnotations();
			Map<String, String> map = new HashMap<String, String>();
			List<Map<String, String>> params = new ArrayList<Map<String, String>>();
			Map<String, String> item = new HashMap<String, String>();
			item.put("name", "客户编号");
			item.put("code", "clientId");
			item.put("value", MsConfig.getClientId());
			item.put("clazz", String.class.getName());
			item.put("required", "true");
			item.put("isShow", "0");
			params.add(item);
			item = new HashMap<String, String>();
			item.put("name", "客户token");
			item.put("code", "token");
			item.put("value", MsConfig.getSercret());
			item.put("clazz", String.class.getName());
			item.put("required", "true");
			item.put("isShow", "0");
			params.add(item);
			List<Map<String, String>> response = new ArrayList<Map<String, String>>();
			for (Annotation annotation : anns) {
				if(annotation instanceof RequestMapping) {
					RequestMapping rm = (RequestMapping) annotation;
					StringBuffer path = new StringBuffer();
					Set<String> set = rmi.getPatternsCondition().getPatterns();
					for (String str : set) {
						path.append(str).append(";");
					}
					if(path.length() > 0) {
						path.setCharAt(path.length() - 1, ' ');
						map.put("name", rm.name());
						map.put("path", path.toString().trim());
						Map<String, Object> methodMap = new HashMap<>();
						methodMap.put("serverMethod", value.getMethod().toString());
						String contentType = MediaType.APPLICATION_FORM_URLENCODED_VALUE;
						Annotation[][] paramAnns = value.getMethod().getParameterAnnotations();
						if (paramAnns.length > 0) {
							Annotation[] cldParamAnns = paramAnns[0];
							for (Annotation cldAnn : cldParamAnns) {
								if(cldAnn instanceof RequestBody) {
									// 请求为json形式
									contentType = MediaType.APPLICATION_JSON_VALUE;
								}
							}
						}
						methodMap.put("parameterContentType", contentType);
						map.put("method", FrameJsonUtil.toString(methodMap));
					}
				} else if(annotation instanceof ApiInfo) {
					ApiInfo ai = (ApiInfo) annotation;
					ApiParam[] aps = ai.params();
					for (ApiParam ap : aps) {
						item = new HashMap<String, String>();
						item.put("name", ap.name());
						item.put("code", ap.code());
						item.put("clazz", ap.clazz().getName());
						item.put("value", ap.value());
						item.put("required", String.valueOf(ap.required()));
						item.put("isShow", "1");
						params.add(item);
					}

					ApiRes[] ars = ai.response();
					for (ApiRes ar : ars) {
						item = new HashMap<String, String>();
						item.put("name", ar.name());
						item.put("code", ar.code());
						item.put("pCode", ar.pCode());
						item.put("clazz", ar.clazz().getName());
						item.put("value", ar.value());
						response.add(item);
					}
				}
			}
			if(map.size() > 0) {
				map.put("params", FrameJsonUtil.toString(params));
				map.put("response", FrameJsonUtil.toString(response));
				data.add(map);
			}
		}
		return data;
	}

	/**
	 * 初始化监控的API
	 * @param appName	为微服务的serviceId
	 * @throws IOException
	 */
	public static void init(final String appName) {
		ApiPrjApiService apiPrjApiService = FrameSpringBeanUtil.getBean(ApiPrjApiService.class);
		List<Map<String, String>> data = findAll();

		try {
			//将之前的修改为未使用
			apiPrjApiService.updateNotUse(appName);
			
			int size = 200;
			int num = data.size() / size;
			if(data.size() % size != 0) {
				num ++;
			}
			for (int i = 0; i < num; i++) {
				int endIdx = (i + 1) * size;
				if((i + 1) == num) {
					endIdx = data.size();
				}
				List<Map<String, String>> cldList = data.subList(i * size, endIdx);
				String detailString = FrameJsonUtil.toString(cldList);
				MsClientResponse<PrjApi> response = apiPrjApiService.saveBatch(appName, detailString);
				final int secondBatchNum = i + 1;
				final int secondNum = num;
				if(ResponseCode.SUCC.getCode() == response.getCode().intValue()) {
					LOGGER.info("成功更新第[{}/{}]批API信息到Monitor!", secondBatchNum, num);
				} else {
					LOGGER.info("更新第[{}/{}]批API信息到Monitor失败: " + response.getMessage(), secondBatchNum, num);
					ThreadPoolTaskExecutor threadPoolTaskExecutor = FrameSpringBeanUtil.getBean(ThreadPoolTaskExecutor.class);
					threadPoolTaskExecutor.execute(new Runnable() {
						@Override
						public void run() {
							try {
								Thread.sleep(25000);
								MsClientResponse<PrjApi> response = apiPrjApiService.saveBatch(appName, detailString);
								if(ResponseCode.SUCC.getCode() == response.getCode().intValue()) {
									LOGGER.info("成功更新第[{}/{}]批API信息到Monitor!", secondBatchNum, secondNum);
								}
							} catch (Exception e) {
							}
						}
					});
				}
			}
		} catch (Exception e) {
			LOGGER.error("更新API信息到Monitor异常: " + e.getMessage(), e);
		}
	}
}